package org.ihelpuoo.io;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;

import org.ihelpuoo.parser.token.CharChecker;
import org.ihelpuoo.parser.token.WhiteSpaceChecker;
import org.ihelpuoo.parser.token.WordBoundaryChecker;

/**
 * <b>TextReader class:</b>
 * <hr color=grey size=1>
 *
 *
 * @ TODO ZZH: think about how to read the un-english words
 *
 * @author zozoh  created @ 2007
 *
 */
public class TextTokenReader extends BufferedReader
{

	public TextTokenReader(Reader in)
	{
		super(in);
		initVariables();
	}

	public TextTokenReader(Reader in, int sz)
	{
		super(in,sz);
		initVariables();
	}

	private void initVariables()
	{
		wordBoundaryChecker = new WordBoundaryChecker();
		wordSkipChecker = new WhiteSpaceChecker();
		whiteSpaceChecker = new WhiteSpaceChecker();
		cacheToken = new StringBuffer();
	}

	private CharChecker		wordBoundaryChecker;
	private CharChecker		wordSkipChecker;
	private CharChecker		whiteSpaceChecker;

	private StringBuffer	cacheToken;

	public void setWordBoundaryChecker(CharChecker wordBoundaryChecker)
	{
		this.wordBoundaryChecker = wordBoundaryChecker;
	}

	public void setWordSkipChecker(CharChecker wordSkipChecker)
	{
		this.wordSkipChecker = wordSkipChecker;
	}

	public CharSequence readToken(CharChecker cc, CharChecker ignore) throws IOException
	{
		StringBuffer sb = new StringBuffer();
		int c = -1;
		int re = 0;
		if (null != ignore)
		{
			while (-1 != (c = read()))
			{
				re = ignore.doCheck(c);
				if (CharChecker.IGNORE_IT == re)
					continue;
				if (CharChecker.MATCHED != re)
					break;
			}
			if (c >= 0)
			{
				re = cc.doCheck(c);
				if (CharChecker.IGNORE_IT != re)
				{
					if (re > 0)
						sb.append((char)re);
					else
						sb.append((char)c);
				}
				if (CharChecker.MATCHED == re && sb.length() > 0)
					return sb;
			}
		}
		while (-1 != (c = read()))
		{
			re = cc.doCheck(c);
			if (CharChecker.IGNORE_IT != re)
			{
				if (re > 0)
					sb.append((char)re);
				else
					sb.append((char)c);
			}
			if (CharChecker.MATCHED == re)
				break;
		}
		return (sb.length() == 0 ? null : sb);
	}

	public String readAll() throws IOException
	{
		StringBuffer sb = new StringBuffer();
		int c;
		while (-1 != (c = read()))
			sb.append((char)c);
		return sb.toString();
	}

	public String readLineIgnoreBlank() throws IOException
	{
		String s;
		while (null != (s = readLine()))
		{
			if (s.trim().length() > 0)
				return s;
		}
		return s;
	}

	public String readWord() throws IOException
	{
		if (cacheToken.length() > 0)
		{
			String re = cacheToken.toString();
			cacheToken = new StringBuffer();
			return re;
		}

		StringBuffer sb = (StringBuffer)readToken(wordBoundaryChecker,wordSkipChecker);
		if (null == sb)
			return null;
		while (sb.length() > 1)
		{
			int lastIndex = sb.length() - 1;
			int c = sb.charAt(lastIndex);
			if (CharChecker.MATCHED == wordBoundaryChecker.doCheck(c))
			{
				if (null == wordSkipChecker || CharChecker.MATCHED != wordSkipChecker.doCheck(c))
					cacheToken.insert(0,(char)c);
				sb.deleteCharAt(lastIndex);
			}
			else
				break;
		}
		return sb.toString();
	}

	public String readScrap() throws IOException
	{
		StringBuffer sb = (StringBuffer)readToken(whiteSpaceChecker,whiteSpaceChecker);
		if (null == sb)
			return null;
		while (sb.length() > 0)
		{
			int lastIndex = sb.length() - 1;
			if (CharChecker.MATCHED == whiteSpaceChecker.doCheck(sb.charAt(lastIndex)))
			{
				sb.deleteCharAt(lastIndex);
			}
			else
				break;
		}
		return sb.toString();
	}

	@Override
	public int read() throws IOException
	{
		if (cacheToken.length() > 0)
		{
			int c = cacheToken.charAt(0);
			cacheToken.deleteCharAt(0);
			return c;
		}
		return super.read();
	}

}
